#!/usr/bin/python3
# -*- coding:utf-8 -*-
""""
@Author: lijk34925
@Time: 2024/3/7 9:48
@File: risk_review_index_config.py
@Function: 风险指标子项配置修改，根据指标名称修改 分级数 和 权重；根据指标规则修改 参数阈值
"""

import re
from qturboframe.lib.utils.by import By
from qturboframe.lib.webdriver import SeleniumError
from BladeFerm.Lib.Common import logger
from BladeFerm.hui2_app import FE
from CommonScripts.common_method_hui_two import open_menu


def risk_review_target_adjust(input_data=None, ui_expect=None):
    # 进入 风险等级查询 菜单 客户风险评估/风险等级查询
    open_menu({'子系统名称': '反洗钱系统', '菜单名称': '客户风险评估/风险评估指标'})
    # 选择 客户类型
    select_value = input_data.pop('客户类型', '个人')
    select = FE.select_table(idname={By.CSS_SELECTOR: 'div.h-selectTable-single'})
    select.set_value_for_single(select_value)
    # 点击 修改
    button_name = "修改"
    weight_modify_flag = False
    rule_modify_flag = False
    # 修改 指标名称 的权重 或 指标规则 的参数阈值
    case_params = deal_input_params(input_data)    # 修改参数
    base_table = FE.table_base(idname={'xpath': './/div[@class="amlrc-tables"]'})
    for key, value in case_params.items():
        childType, childKey = key.split('-')
        if childType == '指标名称':
            pass
            if button_name == '修改':
                button_operate('修改')
                button_name = '保存'
            modify_index_param(childKey, value, base_table.element)
            weight_modify_flag = True
        elif childType == '指标规则':
            rule_modify_flag = modify_rule_params(childKey, value, base_table.element)
        else:
            logger.warning(f"暂只支持修改 指标名称 和 指标规则！标准入参格式是：指标名称-xxxx 或 指标规则-xxxx")
    # 点击 保存 取消
    if button_name == '保存':
        button_operate('保存')
    # 检查结果：权重必须是100%
    if weight_modify_flag:
        check_result()
    # 检出结果：修改规则后的评分
    if rule_modify_flag:
        check_rule_result(ui_expect, base_table.element)


def deal_input_params(input_data: dict):
    global childValues
    result = dict()
    keys = list(input_data.keys())
    if '指标名称' in keys:
        firstKey = '指标名称-' + input_data.get('指标名称')
        firstValue = dict()
        if input_data.get('是否启用', None):
            firstValue.update({'是否启用': input_data.get('是否启用')})
        if input_data.get('指标权重', None):
            firstValue.update({'指标权重': input_data.get('指标权重')})
        if input_data.get('是否启用', None):
            firstValue.update({'分级数': input_data.get('分级数')})
        result[firstKey] = firstValue
    elif '指标规则' in keys:
        secondKey = '指标规则-' + input_data.get('指标规则')
        secondValue = dict()
        if input_data.get('参数阈值', None):
            rangValues = input_data.get('参数阈值')
            if not rangValues.startswith('[') or not rangValues.endswith(']'):
                raise SeleniumError(f'`参数阈值` 入参格式错误！格式必须是：`[1<数量;1<数量<=11;数量<1]`')
            childValues = []
            if re.search(r"=|<=|<", rangValues):
                rangValues.replace("；", ";")
                rangValueList = rangValues[1:-1].split(';')
                for unit in rangValueList:
                    res1 = re.match(r"(\d+)(=|<=|<)(.*?)(=|<=|<)(\d+)", unit)
                    res2 = re.match(r"(\d+)(=|<=|<)(.*?)", unit)
                    res3 = re.match(r"(^[^0-9].*?)(=|<=|<)(\d+)", unit)
                    if res1:
                        childValues.append(list(res1.groups()))
                    elif res2:
                        childValues.append(list(res2.groups()) + ['', ''])
                    elif res3:
                        childValues.append(['', ''] + list(res3.groups()))
                    else:
                        logger.warning(f"入参转换失败！不符合期望格式！")
            else:
                childValues = eval(rangValues)
        secondValue['参数阈值'] = childValues
        if input_data.get('分类评分', None):
            reviewScore = input_data.get('分类评分', '')
            reviewScore.replace("；", ';')
            if not reviewScore.startswith('[') or not reviewScore.endswith(']'):
                raise SeleniumError(f'`分类评分` 入参格式错误！必须是 `[value1;value2;value3]`')
            secondValue['分类评分'] = reviewScore[1:-1].split(';')
        result[secondKey] = secondValue
    else:
        error_info = f"未获得期望参数！必须有 `指标名称` 或 `指标规则`"
        logger.error(error_info)
        raise SeleniumError(error_info)
    logger.info(f"Modify index params : {result}")
    return result


def check_rule_result(ui_expect: dict, body_element):
    for key, value in ui_expect.items():
        row_element = expand_table(key, body_element, 'tr')
        td_element = row_element.find_element_by_attribute(By.XPATH, './td[3]/div/span')
        td_text = td_element.text.split()
        if td_text == str(td_text):
            logger.info(f"检出 {key} 项的分类评分是：{td_text}")
        else:
            error = f"检出 {key} 项的分类评分是：{td_text}，不符合期望！"
            logger.error(error)
            raise SeleniumError(error)


def check_result():
    tar = FE.driver.exist('xpath', './/div[contains(@class,"sum-score")]/span[contains(text(), "权重汇总")]')
    cur_text = tar.text
    cur_weight_score = int(re.search(r'\d+', cur_text).group())
    if cur_weight_score == 100:
        logger.info(f'调整后的结果是100，ok')
    else:
        error = f'调整后的结果是{cur_weight_score}，请检查输入数据'
        logger.warning(error)
        raise SeleniumError(error)


def button_operate(text='修改', father=None):
    '''
    按钮操作和操作后的断言。
    :param text:
    :param father:
    :return:
    '''
    btn = FE.list({By.XPATH: '//div[contains(@class,"search-wrap")]/div[contains(@class,"button-wrap")]'},
                  father=father)
    target_button = btn.fund_elements({By.XPATH: f'./button/span[contains(text(), "{text}")]'},)
    if target_button and len(target_button) == 1:
        target_button[0].click()
        logger.info(f'点击按钮 {text}')
        return True
    elif target_button and len(target_button) > 1:
        target_button[0].click()
        logger.info(f'找到多个按钮，点击第一个按钮 {text} ')
        return True
    else:
        logger.info(f'未找到按钮 {text}')
        return False


def modify_index_param(key: str, value: dict, base_table):
    '''
    修改 指标 的数据
    :param key:
    :param value:
    :param base_table:
    :return:
    '''
    adjust_status = value.get('是否启用', None)
    adjust_level = value.get('分级数', None)
    adjust_weight = value.get('指标权重', None)
    # 展开表格
    target_table_row = expand_table(text=key, father=base_table, parent='tr')
    # 指标 是否启用 设置
    adjust_status = False if adjust_status == '否' else True
    set_status(adjust_status, target_table_row)
    if adjust_level:
        update_adjust_value(key, '分级数', adjust_level, target_table_row)
    # 指标 权重值 设置
    if adjust_weight:
        update_adjust_value(key, '指标权重', adjust_weight, target_table_row)


def modify_rule_params(key: str, value: dict, base_table):
    # 展开表格
    rule_modify_flag = False
    target_tbody = expand_table(text=key, father=base_table, parent='tbody')
    FE.button("编辑", father=target_tbody).click()
    is_child_table = True
    input_element_type_row = '//table[@class="risk-table"]//tr[@class="child-siblings"]'
    second_row_elements = FE.list(target_tbody).fund_elements({By.XPATH: input_element_type_row})
    if second_row_elements:
        first_style = second_row_elements[0].get_attribute("style")
        if re.search(r"display: none", first_style):
            is_child_table = False
    else:
        is_child_table = False
    for secKey, secValue in value.items():
        if secKey == "参数阈值" and is_child_table:
            update_params_range_value(secKey, secValue, target_tbody)
        elif secKey == "参数阈值" and not is_child_table:
            update_params_range_select(secKey, secValue, target_tbody)
        elif secKey == "分类评分":
            rule_modify_flag = True
            update_params_score_value(secKey, secValue, target_tbody)
        else:
            logger.info(f"不期望出现的参数：{secKey}")
    FE.button("保存", father=target_tbody).click()
    return rule_modify_flag


def expand_table(text, father, parent='tbody'):
    '''
    根据 text 查找所在的td单元格，查看是否展开？
    之后返回 td 所在的列表。
    :param text:
    :param father:
    :param parent: 返回的父层节点类型  table  tbody  tr
    :return:
    '''
    unexpand_status = r'h-icon-android-arrow-dropri'
    # onexpand_status = r'h-icon-android-arrow-dropdo'
    xpath_express = f'.//tr/td[contains(text(),"{text}")]'
    base_table_td = father.find_element_by_attribute('xpath', xpath_express)
    base_table_icon = base_table_td.exist('xpath', './i[contains(@class,"h-icon")]')
    if base_table_icon:
        base_table_icon_class = base_table_icon.get_attribute('class').split(' ')
        if unexpand_status in base_table_icon_class:
            base_table_icon.click()
            logger.info(f'展开 {text}')
        else:
            logger.info(f'{text} 已经展开。')
    else:
        logger.warning(f'{text} 没有前缀图标')
    target_ele = base_table_td.find_element_by_attribute('xpath', f'.//ancestor::{parent}[1]')
    return target_ele


def set_status(flag, father):
    '''
    设置 指标状态
    :param flag:
    :param father:
    :return:
    '''
    switch = FE.switch_type({By.XPATH: './/td[4]/span[contains(@class,"h-switch")]'}, father)
    switch.set_status(flag)


def update_adjust_value(name, key, score, father):
    '''
    设置 指标得分
    :param name: 指标名称
    :param key: 子项名称
    :param score: 指标得分
    :param father:
    :return:
    '''
    index = 2 if key == '分级数' else 3
    input_xpath = f'./td[{index}]//div[@type="text" and contains(@class, "h-input-number")]'
    input_element = FE.input_type({By.XPATH: input_xpath}, father=father, model='number')
    if input_element.element:
        input_element.clear()
        input_element.set_value(str(score))
        logger.info(f'设置指标 {name} 的 {key} 项的值为 {score}')
    else:
        raise SeleniumError(f'指标 {name} 的 {key} 项不存在调整输入框，请检查！')


def update_params_range_value(indexName, value, target_tbody):
    """
    更新参数阈值。待处理的参数阈值的取值格式是：
        参数阈值:
          - "1,=,数量属性,,"
          - "2,<=,数量属性,<=,5"
          - "5,<,数量属性,,"
    """
    for i, line in enumerate(value):
        logger.info(f'开始填充第 {i} 行的阈值 ： {line}')
        row_ele_xpath = f'//table[@class="risk-table"]/tr[{i+2}]//table/tr[@class="child-siblings"]'
        row_ele = target_tbody.find_element_by_attribute(By.XPATH, row_ele_xpath, timeout=1)
        cols_ele = row_ele.find_elements_by_attribute(By.XPATH, './td', timeout=1)
        if len(cols_ele) == 5:
            values = line.split(',')
            if values[0]:
                pre_input_ele_xpath = f'./td[1]//div[contains(@class,"h-input-wrapper")]'
                FE.input_type({By.XPATH: pre_input_ele_xpath}, father=row_ele).set_value(values[0])
            if values[1]:
                pre_input_ele_xpath = f'./td[2]//div[contains(@class,"h-selectTable-single")]'
                FE.select_table({By.XPATH: pre_input_ele_xpath}, father=row_ele).set_value_for_single(values[1])
            if values[3]:
                pre_input_ele_xpath = f'./td[4]//div[contains(@class,"h-selectTable-single")]'
                FE.select_table({By.XPATH: pre_input_ele_xpath}, father=row_ele).set_value_for_single(values[3])
            if values[4]:
                pre_input_ele_xpath = f'./td[5]//div[contains(@class,"h-input-wrapper")]'
                FE.input_type({By.XPATH: pre_input_ele_xpath}, father=row_ele).set_value(values[4])
            logger.info(f'设置第{i+1}行值为：{line}')
        elif len(cols_ele) == 3:
            pre_input_ele_xpath = f'./td[3]//div[contains(@class,"h-selectTable-multiple")]'
            FE.select_table({By.XPATH: pre_input_ele_xpath}, father=row_ele).set_value_for_multiple(line)
        else:
            logger.warning(f'入参数据错误!')
    logger.info(f'调整规则 {indexName} 的阈值为： {value}')


def update_params_range_select(indexName, value, target_tbody):
    """
    修改参数阈值，修改框就跟在细分项后。参数取值格式为多选输入框的格式
    """
    for i, line in enumerate(value):
        logger.info(f'开始填充第 {i} 行的阈值 ： {line}')
        input_element_type_row = f'//table[@class="risk-table"]/tr[{i+2}]/td/table/tr[1]'
        first_title_row = FE.list(target_tbody).fund_elements({By.XPATH: input_element_type_row})
        row_elements_xpath = './td[2]//div[contains(@class,"h-selectTable-multiple")]'
        FE.select_table({By.XPATH: row_elements_xpath}, father=first_title_row[0]).set_value_for_multiple([line])
        logger.info(f"设置指标规则 {indexName} 的参数阈值为： {line}")



def update_params_score_value(indexName, value, target_tbody):
    """
    分类评分 的值修改
    """
    for i, line in enumerate(value):
        logger.info(f'开始填充第 {i} 行的阈值 ： {line}')
        row_ele_xpath = f'//table[@class="risk-table"]/tr[{i+2}]//table/tr[@class="child-siblings"]'
        row_ele = target_tbody.find_element_by_attribute(By.XPATH, row_ele_xpath, timeout=1)
        row_elements_xpath = './preceding-sibling::tr/td[3]//div[contains(@class,"amlrc-input")]'
        FE.input_number({By.XPATH: row_elements_xpath}, father=row_ele).set_value(line)
        logger.info(f"设置指标规则 {indexName} 的分类评分为： {line}")